package com.alpha.service.config;

import com.alpha.core.http.Response;
import com.alpha.core.utils.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.bind.support.WebExchangeBindException;
import org.springframework.web.server.ServerWebInputException;

import java.util.Date;


/**
 * 公共全局异常处理器
 *
 * @author chenruwan
 * @since 2022-01-01
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    private static final String EXCEPTION_HINT = "Caught Exception : ";

    /**
     * spring映射或解析RequestBody失败
     */
    @ExceptionHandler(ServerWebInputException.class)
    public Response<Object> serverWebInputException(ServerWebInputException e) {
        log.error(EXCEPTION_HINT, e);
        return Response.failure(HttpStatus.BAD_REQUEST, e.getReason());
    }

    /**
     * 缺少必填参数，通常由Assert抛出
     */
    @ExceptionHandler(IllegalArgumentException.class)
    public Response<Object> illegalArgumentException(IllegalArgumentException e) {
        log.error(EXCEPTION_HINT, e);
        return Response.failure(HttpStatus.BAD_REQUEST, e.getMessage());
    }

    /**
     * spring @Validated注解校验失败
     */
    @ExceptionHandler(WebExchangeBindException.class)
    public Response<Object> webExchangeBindException(WebExchangeBindException e) {
        log.error(EXCEPTION_HINT, e);

        FieldError fieldError = e.getBindingResult().getFieldError();
        if (fieldError == null || fieldError.getDefaultMessage() == null) {
            return Response.failure(HttpStatus.BAD_REQUEST, e.getReason());
        }

        return Response.failure(HttpStatus.BAD_REQUEST, fieldError.getDefaultMessage());
    }

    /**
     * SQL 语法错误
     */
    @ExceptionHandler(BadSqlGrammarException.class)
    public Response<Object> badSqlGrammarException(BadSqlGrammarException exception) {
        log.error(EXCEPTION_HINT, exception);
        return Response.failure(HttpStatus.INTERNAL_SERVER_ERROR, "SQL语法错误", exception.getCause().getMessage());
    }

    /**
     * 空指针异常
     */
    @ExceptionHandler(NullPointerException.class)
    public Response<Object> nullPointerException(NullPointerException exception) {
        log.error(EXCEPTION_HINT, exception);
        return Response.failure(HttpStatus.INTERNAL_SERVER_ERROR, "系统异常，请联系客服，服务器当前时间：" +
                DateUtil.format(new Date(), DateUtil.NORM_DATETIME_PATTERN));
    }

    /**
     * 其他异常
     */
    @ExceptionHandler(Exception.class)
    public Response<Object> exception(Exception e) {
        log.error(EXCEPTION_HINT, e);
        return Response.failure(HttpStatus.INTERNAL_SERVER_ERROR, e.getLocalizedMessage());
    }
}
